<?php
/**
 * ***********************************************************************************
 * 咨询鲤 PC端知识店铺-题库相关
 * 
 * @author Mr.RJH
 * @date 2025-09-09
 * @email<15213026209@163.com>
 * ***********************************************************************************
 */
namespace app\controller;

use app\BaseController;

use think\facade\Db;
use app\model\merchant\ConfigModel;
use app\model\product\ZxlKnowStoreProductModel;
use app\model\product\ZxlKnowStoreProductAttrModel;
use app\model\product\ZxlKnowStoreCategoryModel;

use app\model\question\ZxlKnowStoreQuestionChapterModel;
use app\model\question\ZxlKnowStoreQuestionSetModel;
use app\model\question\ZxlKnowStoreQuestionModel;
use app\model\question\ZxlKnowStoreQuestionMaterialModel;
use app\model\question\ZxlKnowStoreQuestionCollectModel;
use app\model\question\ZxlKnowStoreQuestionCorrectionModel;
use app\model\question\ZxlKnowStoreQuestionNoteModel;
use app\model\question\ZxlKnowStoreQuestionNoteLikeLogModel;
use app\model\question\ZxlKnowStoreQuestionPracticeModel;
use app\model\question\ZxlKnowStoreQuestionPracticeDetailModel;
use app\model\question\ZxlKnowStoreQuestionUserStatisticsModel;

use app\model\user\ZxlKnowStorePowerModel;
use app\model\user\ZxlKnowStoreCollectModel;
use app\model\user\ZxlKnowStoreUserBaseModel;

use app\service\ProductService;
use app\service\KnowStoreApiService;

class Question extends BaseController
{
    /**
     * 题库列表
     * 
     * @return mixed
     */
    public function index()
    {
        if ($this->request->isPost()) {

            $limit = $this->request->param('limit');
            $page = $this->request->param('page',1);
            $cate_level = $this->request->param('cate_level', 2);
            $cate_id = $this->request->param('category_id', '');

            $m_id = $this->request->m_id;
            try {
                $productService = new ProductService($m_id);
                $list = $productService->get_product_list(5, $limit, $page, $cate_id, $cate_level);
                foreach ($list['data'] as &$v) {
                    $v['head_imgs'] = $v['head_imgs'] ? explode(',',$v['head_imgs'])[0] : '/static/images/no_pic_1.png';
                    $v['tags'] = ZxlKnowStoreProductModel::get_tag_list($v['tags']);
                }
                
            } catch (\Exception $e) {
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
            return json(['code' => 0,'msg' => 'SUCCESS','count' => $list['total'],'data' => $list['data']]);
        }
        // 获取分类
        $first_category = ZxlKnowStoreCategoryModel::first_category($this->request->m_id, 4);

        $this->assign('first_category', $first_category);
        return $this->fetch();
    }

    /**
     * 题库章节详情页
     * 
     * @return mixed
     */
    public function chapter_detail()
    {
        $id = $this->request->param('id');
        // 获取该题库是否购买
        $is_buy = ZxlKnowStorePowerModel::getPowerDetail($id, $this->user_id);
        
        $info = ZxlKnowStoreProductModel::getInfo($this->request->m_id, $id, $is_buy);
        if (!$info) {
            return redirect('/error/http404');
        }
        
        // 获取相同题库
        $question_names = $this->get_question_names($id);

        // 题库推荐商品
        $info['recommend_list'] = [];
        if ($info['recommend_product_ids']) {
            $recommend_list = ZxlKnowStoreProductModel::with("attrMinPrice")->whereIn('id', $info['recommend_product_ids'])
                            ->whereIn('product_type',ZxlKnowStoreProductModel::PC_PRODUCTTYPE)
                            ->field('id,name,sub_title,product_type,head_imgs,background_color,real_sales,virtual_sales,tags')
                            ->select()->toArray();

            foreach ($recommend_list as &$v) {
                if ($v['product_type'] == 10) {
                    $v['head_imgs'] = '/static/images/exam.png';
                } else {
                    $v['head_imgs'] = $v['head_imgs'] ? explode(',',$v['head_imgs'])[0] : '/static/images/no_pic_1.png';
                }
                $v['product_type_text'] = ZxlKnowStoreProductModel::getPcProductType($v['product_type']);
                $v['href'] = ZxlKnowStoreProductModel::getPcProductDetailHref($v['product_type'], $v['id']);
                
            }
            $info['recommend_list'] = $recommend_list;
        }
        
        if ($is_buy == 1 || $info['sale_price'] <= 0) {
            $info['href'] = '/question/chapter_practice?product_id='.$id;
        } else {
            $info['href'] = '/question/detail?product_id='.$id;
        }
        // 推荐题库
        $productService = new ProductService($this->request->m_id);
        $question_list = $productService->recommend_product(5, 4);
        
        $this->assign('question_list', $question_list);
        $this->assign('question_names', $question_names);
        $this->assign('info', $info);
        return $this->fetch();
    }

    /**
     * 根据题库分类获取相同题库
     * 
     * @param int $product_id
     * @return json
     */
    public function get_question_names($product_id)
    {
        $m_id = $this->request->m_id;
        $where = function($q)use($m_id, $product_id){
            $q->where('m_id', $m_id);
            $q->where('status', 1);
            $q->where('is_delete', 0);
            $q->where('product_type', 5);
        };
        $cate_id = ZxlKnowStoreProductModel::where('id',$product_id)->value('cate_id');
        if($cate_id){
            // 存在分类查询相同分类
            $cat_ids = explode(',',$cate_id);
            $product_list = [];
            foreach ($cat_ids as $catid){
                $chids = ZxlKnowStoreProductModel::where($where)->where("FIND_IN_SET(".$catid.", cate_id)")->field('id, name, COALESCE(NULLIF(sub_title, ""), name) as sub_title')->select()->toArray();
                foreach ($chids as &$val){
                    $product_list[] = $val;
                }
            }
        }else{
            $product_list = ZxlKnowStoreProductModel::where($where)
            ->where(function($q){
                $q->whereNull('cate_id')
                ->whereOr('cate_id', '');
            })->field('id, name, COALESCE(NULLIF(sub_title, ""), name) as sub_title')->select()->toArray(); 
        }
        return $product_list;
    }

    /**
     * 获取题库章节
     * 
     * @return json
     */
    public function get_chapters()
    {
        if ($this->request->isPost()) {
            $page = $this->request->param('page');
            $limit = $this->request->param('limit', 10);
            $product_id = $this->request->param('product_id');
            try {
                $list = ZxlKnowStoreQuestionChapterModel::getAllchapter(ZxlKnowStoreProductModel::getMainProductId($product_id), $this->user_id, $page, $limit);
            } catch (\Exception $e) {
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
            return json(['code' => 0, 'msg' => 'SUCCESS', 'count' => $list['total'], 'data' => $list['data']]);
        }
    }

    /**
     * 重置做题进度
     * 
     * @return json
     */
    public function reset_chapter_process()
    {
        if ($this->request->isPost()) {
            $chapter_id = $this->request->param('chapter_id');
            try {
                $target_ids = ZxlKnowStoreQuestionChapterModel::whereOr('id', $chapter_id)->whereOr('pid', $chapter_id)->column('id');
                ZxlKnowStoreQuestionPracticeDetailModel::whereIn('main_id', $target_ids)->update(['is_statics' => 0, 'update_time' => time()]);
                // 重新统计做题进度
                $chapter = ZxlKnowStoreQuestionChapterModel::where('id', $chapter_id)->find();

                ZxlKnowStoreQuestionUserStatisticsModel::UpdateUserData($chapter, $this->user_id, $this->request->m_id, $chapter->lib_id);
            } catch (\Exception $e) {
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
            return json(['code' => 0,'msg' => '重置成功']);
        }
        
    }

    /**
     * 题库刷题设置
     * 
     * @return mixed
     */
    public function practice_set()
    {
        $user_base = ZxlKnowStoreUserBaseModel::where('user_id', $this->user_id)->find();
        if ($this->request->isPost()) {
            $post = $this->request->post();
            try {
                $self_setting = json_decode($user_base['self_setting'],true);
                $self_setting['practiceNum'] = $post['practice_num'];
                $self_setting['practicetype'] = $post['practice_type'];
                $self_setting['practicemode'] = $post['practice_mode'];
                $user_base->self_setting = json_encode($self_setting);
                if ($user_base->save()) {
                    return json(['code' => 0,'msg' => '保存成功']);
                } else {
                    return json(['code' => 1,'msg' => '保存失败']);
                }
            } catch (\Exception $e) {
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
        }
        // 如果设置信息为空 就强行设置为默认配置
        if(!$user_base['self_setting']){
            $question_set = ZxlKnowStoreQuestionSetModel::where('m_id', $this->request->m_id)->find();
            $data = [
                "nightType" => 0,
                "nextQuestion" => 0,
                "autoAnswer" => 0,
                "practiceNum" => $question_set->random_exercise_num ?? 10,
                "wrongNum" => $question_set->error_retrain_num ?? 10,
                "practicetype" => $question_set->extracting_mode ?? 0,
                "practicemode" => $question_set->doing_exercises_mode ?? 0
            ];
            $user_base->self_setting = json_encode($data);
            $user_base->save();
        }
        $set = json_decode($user_base['self_setting'],true);

        $this->assign('set', $set);
        $this->assign('getPracticeNum', ZxlKnowStoreQuestionSetModel::getPracticeNum());
        $this->assign('getPracticeType', ZxlKnowStoreQuestionSetModel::getPracticeType());
        $this->assign('getPracticeMode', ZxlKnowStoreQuestionSetModel::getPracticeMode());
        return $this->fetch();
    }

    /**
     * 题库详情
     * 
     * @return mixed
     */
    public function detail()
    {
        $id = $this->request->param('product_id');
        $info = ZxlKnowStoreProductModel::getInfo($this->request->m_id, $id);
        if (!$info) {
            return redirect('/error/http404');
        } else {
            $info->visit_num += 1; // 增加访问量
            $info->save();

            $info['head_imgs'] = $info['head_imgs'] ? explode(',', $info['head_imgs']) : '/static/images/no_pic_1.png';
            if ($info['tags']) {
                $info['tags'] = json_decode($info['tags'], true);
            }
            $info['attr'] = ZxlKnowStoreProductAttrModel::where(['product_id' => $info['id'], 'status' => 1, 'is_delete' => 0])->order('sale_price asc')->select()->toArray();

            // 是否收藏
            $info['is_favorites'] = 0;
            $favorites = ZxlKnowStoreCollectModel::where(['user_id' => $this->user_id, 'product_id' => $info['id']])->find();
            if ($favorites) {
                $info['is_favorites'] = 1;
            }
        }
        // 购课须知
        $notice = ConfigModel::getConfigValue('notice')[1];

        $productService = new ProductService($this->request->m_id);
        // 相关题库
        $related_list = $productService->rand_recommend_product(10, 5);
        
        $this->assign('info', $info);
        $this->assign('notice', $notice);
        $this->assign('related_list', $related_list);
        return $this->fetch();
    }

    /**
     * 章节练习
     * 
     * @return mixed
     */
    public function chapter_practice()
    {
        $product_id = $this->request->param('product_id');
        $chapter_id = $this->request->param('chapter_id'); 
        $source = $this->request->param('source', 'practice'); // 来源 practice：练习 report：报告
        $question_index = $this->request->param('question_index', 0); // 练题报告，传过来答题卡key值
        $practice_id = $this->request->param('practice_id', ''); // 练题报告，传过来的练习ID

        // 是否购买
        $is_buy = ZxlKnowStorePowerModel::getPowerDetail($product_id, $this->user_id);
        // 产品信息
        $info = ZxlKnowStoreProductModel::getInfo($this->request->m_id, $product_id, $is_buy);

        // 章节名称
        $info['chapter_name'] = ZxlKnowStoreQuestionChapterModel::getChapterName($chapter_id);
        
        // 获取刷题设置
        $set = ZxlKnowStoreUserBaseModel::getSelfSetting($this->user_id);
        $count = isset($set['practiceNum']) ? $set['practiceNum'] : 10;
        $mode = isset($set['practicetype']) ? $set['practicetype'] : 0; // 0：随机抽题 1：顺序抽题
        $info['set'] = $set;
        
        if ($practice_id) { // 练习报告过来
            $practice = ZxlKnowStoreQuestionPracticeModel::find($practice_id);
            $question_ids = explode(',', $practice['question_ids']);

            // 错题
            if ($source == 'report_wrong') {
                $question_ids = ZxlKnowStoreQuestionPracticeDetailModel::where(['practice_id' => $practice_id, 'is_correct' => 0, 'user_id' => $this->user_id])->whereIn('question_id', $question_ids)->column('question_id');
            }
            // 答题卡详情
            $info['question_list'] = $this->get_answer_card_detail($question_ids, $practice_id);
            
            $info['practice_id'] = $practice_id;
        } else {
            // 出题
            $question_ids = $this->chapter_question($product_id, $chapter_id);
            // 插入做题记录
            $info['practice_id'] = ZxlKnowStoreQuestionPracticeModel::save_practice($this->user_id, $this->request->m_id, $info['id'], $chapter_id, count($question_ids), 'chapter', $question_ids, $mode);
        }
        $info['total_question'] = count($question_ids);
        if (!$info || !$question_ids) {
            return redirect('/error/http404');
        }
        
        $this->assign('source', $source);
        $this->assign('question_ids', $question_ids);
        $this->assign('question_index', intval($question_index));
        $this->assign('info', $info);
        return $this->fetch();
    }

    /**
     * 获取该章节下的一部分题目
     * 返回数量通过用户自行设置
     * 
     * @param $product_id 产品ID
     * @param $chapter_id 章节ID
     * @return array
     */
    private function chapter_question($product_id, $chapter_id){
        // 获取刷题设置
        $set = ZxlKnowStoreUserBaseModel::getSelfSetting($this->user_id);
        $practice_num = $set['practiceNum'] ? $set['practiceNum'] : 10;
        $practice_type = $set['practicetype'] ? $set['practicetype'] : 0; // 0：随机抽题 1：顺序抽题
        
        $chapter = ZxlKnowStoreQuestionChapterModel::with(['children'])->where("id", $chapter_id)->append(['chapter_name'])->find();
        if ($chapter) {
            $ids = ZxlKnowStoreQuestionModel::chapterQuestion($chapter, $practice_num, $this->user_id, $practice_type);
        }
        return $ids ?? []; 
    }
    
    /**
     * 获取题目详情
     * 
     * @return json
     */
    public function get_question_info()
    {
        if ($this->request->isPost()) {
            $question_id = $this->request->param('question_id');
            $practice_id = $this->request->param('practice_id');
            $source = $this->request->param('source'); // 来源 practice：练习 report：报告
            try {

                $field = 'id, m_id, question, options, type, difficulty, material_id, chapter_id, answer, analyze, lib_id';
                $info = ZxlKnowStoreQuestionModel::where('id', $question_id)->field($field)->find();
                if ($info) {
                    $info['answer'] = implode(',', json_decode($info['answer'], true));
                    if ($info['material_id'] > 0) {
                        // 材料题
                        $info['type'] = 9;
                        $info['type_name'] = ZxlKnowStoreQuestionModel::get_type($info['type']);
                        $material = ZxlKnowStoreQuestionMaterialModel::find($info['material_id']);
                        $info['material'] = $material['content'];
                        $info['question_voice'] = $material['question_voice'];
                        // 查询当前材料的所有问题
                        $questions = ZxlKnowStoreQuestionModel::where("material_id", $info['material_id'])->field($field)->select()->toArray();
                        foreach ($questions as &$val) {
                            $val['answer'] = implode(',', json_decode($val['answer'], true));
                            $val['options'] = json_decode($val['options'], true);
                            $val['type_name'] = ZxlKnowStoreQuestionModel::get_type($val['type']);
                            // 获取做题详情
                            $val['practice_detail'] = ZxlKnowStoreQuestionPracticeDetailModel::get_user_practice_detail($practice_id, $this->user_id, $val['id']);

                            // 根据模式去除解析与正确答案
                            $this->get_answer_hide($val, $source);
                        }
                        $info['children'] = $questions;
                    }
                    // 获取做题详情
                    $info['practice_detail'] = ZxlKnowStoreQuestionPracticeDetailModel::get_user_practice_detail($practice_id, $this->user_id, $info['id']);
                    $info['options'] = json_decode($info['options'], true);
                    
                    $info['is_collect'] = ZxlKnowStoreQuestionCollectModel::where(['question_id' => $question_id, 'user_id' => $this->user_id])->find();

                    $info['type_name'] = ZxlKnowStoreQuestionModel::get_type($info['type']);
                    // 根据模式去除解析与正确答案
                    $this->get_answer_hide($info, $source);
                    
                }
            } catch (\Exception $e) {
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
            return json(['code' => 0,'msg' => 'SUCCESS', 'data' => $info]);
        }
    }

    /**
     * 隐藏正确答案与解析
     * 
     * @return array $info 题目详情
     * @return string
     */
    private function get_answer_hide($info, $source)
    {
        // 获取刷题设置
        $set = ZxlKnowStoreUserBaseModel::getSelfSetting($this->user_id);
        if ($set['practicemode'] == 0 && $source == 'practice') { // 考试模式
            $info['answer'] = '';
            $info['analyze'] = '';
        }
        return $info;
    }

    /**
    * 题目收藏和取消收藏
    * 
    * @return json
    */
    public function favorites_add()
    {
        if ($this->request->isPost()) {
            Db::startTrans();
            try {
                $question_id = $this->request->param('question_id');
                $practice_type = $this->request->param('practice_type', '');
                $practice_id = $this->request->param('practice_id');

                $question = ZxlKnowStoreQuestionModel::find($question_id);
                // 做题记录
                $practice = ZxlKnowStoreQuestionPracticeModel::find($practice_id);

                $model = ZxlKnowStoreQuestionCollectModel::where(['question_id' => $question_id, 'user_id' => $this->user_id])->findOrEmpty();
                if($model->isEmpty()){
                    $model->question_id = $question_id;
                    $model->user_id = $this->user_id;
                    $model->m_id = $this->request->m_id;
                    $model->question_type = $question['type'];
                    $model->practice_type = $practice_type;
                    $model->target_id = $practice['target_id'];
                    $model->practice_id = $practice_id;
                    $model->lib_id = ZxlKnowStoreProductModel::getMainProductId($question['lib_id']);
                    $model->chapter_id = $question['chapter_id'];
                    $model->save();
                    $msg = '收藏成功';
                    $is_collect = 1;
                } else {
                    $model->delete();
                    if($question['material_id'] > 0) {
                        $question_ids = ZxlKnowStoreQuestionModel::where('material_id', $question['material_id'])->column('id');
                        ZxlKnowStoreQuestionCollectModel::where(['user_id'=>$this->userId])->whereIn('question_id', $question_ids)->delete();
                    }
                    $msg = '已取消收藏';
                    $is_collect = 0;
                }
            } catch (\Exception $e) {
                Db::rollback();
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
            Db::commit();
            return json(['code' => 0,'msg' => $msg, 'data' => $is_collect]);
        }
    }

    /**
     * 题目纠错
     * 
     * @return mixed
     */
    public function correction()
    {
        if ($this->request->isPost()) {
            $post = $this->request->post();

            Db::startTrans();
            try {
                $question = ZxlKnowStoreQuestionModel::find($post['question_id']);
                if (!$question) {
                    return json(['code' => 1,'msg' => '题目查询失败，请刷新重试']);
                }
                $post['m_id'] = $this->request->m_id;
                $post['user_id'] = $this->user_id;
                $post['lib_id'] = $question['lib_id'];
                $post['create_time'] = date('Y-m-d H:i:s');
                $result = ZxlKnowStoreQuestionCorrectionModel::insert($post);
                if ($result) {
                    Db::commit();
                    return json(['code' => 0,'msg' => '谢谢您的反馈！我们会尽快处理']);
                } else {
                    Db::rollback();
                    return json(['code' => 1,'msg' => '提交失败']);
                }
            } catch (\Exception $e) {
                Db::rollback();
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
        }
        
        $question_id = $this->request->param('question_id');

        $this->assign('question_id', $question_id);
        $this->assign('getType', ZxlKnowStoreQuestionCorrectionModel::getType());
        return $this->fetch();
    }

    /**
     * 获取公开题目笔记
     * 
     * @return json
     */
    public function get_note()
    {
        if ($this->request->isPost()) {
            $limit = $this->request->param('limit', 10);
            $page = $this->request->param('page',1);
            $question_id = $this->request->param('question_id');
            try {

                $list = ZxlKnowStoreQuestionNoteModel::getNoteList($question_id, $this->user_id, $limit, $page);
            } catch (\Exception $e) {
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
            return json(['code' => 0,'msg' => 'SUCCESS','count' => $list['total'],'data' => $list['data']]);
        }
    }

    /**
     * 写笔记
     * 
     * @return json
     */
    public function note()
    {
        if ($this->request->isPost()) {
            $post = $this->request->post();
            Db::startTrans();
            try {
                $question = ZxlKnowStoreQuestionModel::find($post['question_id']);
                if (!$question) {
                    return json(['code' => 1,'msg' => '题目查询失败，请刷新重试']);
                }
                if (!isset($post['is_public'])) {
                    $post['is_public'] = 0;
                }
                $post['m_id'] = $this->request->m_id;
                $post['user_id'] = $this->user_id;
                $post['lib_id'] = $question['lib_id'];
                $post['chapter_id'] = $question['chapter_id'];
                $post['create_time'] = time();
                $result = ZxlKnowStoreQuestionNoteModel::insert($post);
                if ($result) {
                    Db::commit();
                    return json(['code' => 0,'msg' => '保存成功']);
                } else {
                    Db::rollback();
                    return json(['code' => 1,'msg' => '保存失败']);
                }
            } catch (\Exception $e) {
                Db::rollback();
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
        }
        $question_id = $this->request->param('question_id');
        $id = $this->request->param('id');

        $info = ZxlKnowStoreQuestionNoteModel::find($id);

        $this->assign('info', $info);
        $this->assign('question_id', $question_id);
        return $this->fetch();
    }

    /**
     * 笔记点赞/取消
     * 
     * @return json
     */
    public function note_like()
    {
        if ($this->request->isPost()) {
            $note_id = $this->request->param('note_id');
            Db::startTrans();
            try {
                $note_info = ZxlKnowStoreQuestionNoteModel::where('id', $note_id)->find();
                if($note_info) {
                    // 查询当前是否已经点赞
                    $log = ZxlKnowStoreQuestionNoteLikeLogModel::where(['user_id' => $this->user_id, 'note_id' => $note_id])->findOrEmpty();
                    if($log->isEmpty()) {
                        //点赞并记录
                        $note_info->like +=1;
                        $log->user_id = $this->user_id;
                        $log->note_id = $note_id;
                        $log->question_id = $note_info['question_id'];
                        $log->create_time = time();
                        $log->update_time = time();
                        $log->save();

                        $is_like = 1;
                        $msg = '点赞成功';
                    } else {
                        // 取消点赞
                        $is_like = 0;
                        $note_info->like -=1;
                        $note_info->like < 0 ? 0 : $note_info->like;
                        $log->delete();
                        $msg = '已取消点赞';
                    }
                    $note_info->save();
                    Db::commit();
                    return json(['code' => 0,'msg' => $msg, 'data' => $is_like]);
                } else {
                    Db::rollback();
                    return json(['code' => 1,'msg' => '查询笔记错误，请刷新页面重试']);
                }
            } catch (\Exception $e) {
                Db::rollback();
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
        }
    }

    /**
     * 提交问题答案
     * 
     * @return json
     */
    public function submit_answer()
    {
        if ($this->request->isPost()) {
            $question_id = $this->request->param('question_id', 0);
            $answer = $this->request->param('answer_'.$question_id, []);
            $practice_id = $this->request->param('practice_id', 0);
            $is_end = $this->request->param('is_end', 0);
            
            Db::startTrans();
            try {
                $practice = ZxlKnowStoreQuestionPracticeModel::find($practice_id);
                if(!$practice) {
                    return json(['code' => 1,'msg' => '记录答案错误，请刷新页面重试']);
                }
                // 获取刷题设置
                $set = ZxlKnowStoreUserBaseModel::getSelfSetting($this->user_id);
                if ($set['practicemode'] == 1) {
                    // 背题模式
                    $answer = [];
                }
                
                $answer = array_values($answer);
                
                // 记录刷题记录
                $log = ZxlKnowStoreQuestionPracticeDetailModel::addLog($question_id, $answer, $practice);
                
                if ($set['practicemode'] == 0 || $set['practicemode'] == 2) { // 考试模式 、练题模式
                    $data['is_correct'] = $log->is_correct; 
                } else {
                    $data['is_correct'] = 1;
                }
                $data['answer'] = json_decode($log->answer, true); 

                // 结束练习
                if ($is_end == 1) {
                    $this->submit_practice($set, $practice);
                }
                
                Db::commit();
                return json(['code' => 0,'msg' => 'SUCCESS', 'data' => $data]);
            } catch (\Exception $e) {
                Db::rollback();
                return json(['code' => 1,'msg' => $e->getMessage()]);
            }
        }
    }

    /**
     * 结束练习
     * 
     * @param $user_base 刷题设置
     * @param $practice 练习记录
     * @return json
     */
    private function submit_practice($set, $practice)
    {
        // 获取已练习数量
        $practice_count = ZxlKnowStoreQuestionPracticeDetailModel::where(['user_id' => $this->user_id, 'practice_id' => $practice['id']])->where('answer', '<>', '[]')->count();
        if ($set['practicemode'] == 0) {
            if ($practice_count < $practice['total_question']) {
                throw new \Exception('你还有未完成的题目，请完成后再交卷');
            }
        }
        // 此次训练正确数量
        $rightCount = ZxlKnowStoreQuestionPracticeDetailModel::where(["practice_id" => $practice['id'], "is_correct" => 1])->count();
        //计算正确率 n%
        $rate = 0;
        $totalNum = ZxlKnowStoreQuestionPracticeDetailModel::where(["practice_id" => $practice['id']])->count();
        if($practice->total_question > $totalNum) $totalNum = $practice->total_question;
        
        if($rightCount > 0 && $totalNum > 0){
            $rate = bcmul(bcdiv($rightCount, $totalNum, 4), 100, 2);
        }
        $practice->score = 0;
        $practice->correct_rate = $rate;
        $practice->update_time = time();
        $practice->sub_time = time();
        $practice->status = 1;
        $practice->save();

        return true;
    }

    /**
     * 练习报告
     * 
     * @return mixed
     */
    public function practice_report()
    {
        $practice_id = $this->request->param('practice_id'); // 练习ID
        $info = ZxlKnowStoreQuestionPracticeModel::find($practice_id);
        if (!$info) {
            return redirect('/error/http404');
        }
        // 练习章节
        $chapter = ZxlKnowStoreQuestionChapterModel::find($info['target_id']);
        $info['chapter_name'] = $chapter['name'];

        // 答对数
        $info['success_count'] = ZxlKnowStoreQuestionPracticeDetailModel::where(['practice_id' => $info['id'], 'is_correct' => 1])->count();
        
        // 练习题数
        $question_ids = explode(',', $info['question_ids']);

        // 答题卡详情
        $info['question_list'] = $this->get_answer_card_detail($question_ids, $info['id']);

        // 做题用时
        $show_time = bcsub($info['sub_time'], $info['create_time']);
        $info['show_time'] = $show_time > 0 ? show_time_format($show_time) : '--';

        // 获取刷题设置
        $info['set'] = ZxlKnowStoreUserBaseModel::getSelfSetting($this->user_id);

        $this->assign('info', $info);
        return $this->fetch();
    }

    /**
     * 获取答题卡详情 正确/错误
     * 
     * @param $question_ids 题目ID
     * @param $practice_id 已练习ID
     * @return array
     */
    private function get_answer_card_detail($question_ids, $practice_id)
    {
        $question_list = [];
        foreach ($question_ids as $key => $v) {
            $question_list[$key]['question_id'] = $v;

            $question_list[$key]['is_correct'] = '';
            $detail = ZxlKnowStoreQuestionPracticeDetailModel::where(['practice_id' => $practice_id, 'question_id' => $v, 'user_id' => $this->user_id])->find();
            if ($detail) {
                $question_list[$key]['is_correct'] = $detail['is_correct'];
            }
        }
        return $question_list;
    }
}